package nl.grol.yakshop.domain.repository;

import java.net.URL;
import java.util.List;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import nl.grol.yakshop.dataimporter.HerdImporterI;
import nl.grol.yakshop.domain.model.ProcessedOrder;
import nl.grol.yakshop.domain.model.YakHerd;
import nl.grol.yakshop.util.YakShopException;
import nl.grol.yakshop.web.util.RequestContextHolder;

import com.google.inject.Inject;

public class Repository implements RepositoryI {
    private static final Logger LOGGER = Logger.getLogger(Repository.class.getName());
	private PersistenceManager pm;

	private HerdImporterI importer;
	private YakHerd herd;

	@Inject
	public Repository(HerdImporterI importer) {
        this.pm = RequestContextHolder.getPersistanceManager();
		this.importer = importer;
	}

	@Override
	public YakHerd getHerd() throws YakShopException {
		if (this.herd == null) {
			/*
			 * For now use the example herd from file ${PROJECT}/src/herd.xml
			 */
			URL resource = getClass().getClassLoader().getResource("herd.xml");
			this.herd = importer.loadFromResource( resource );
		}

		return herd;
	}

	public void persistProcessedOrder( ProcessedOrder processedOrder ) throws YakShopException {
		
		LOGGER.info("Persisting order:" + processedOrder.toString() );
		try {
			pm.makePersistent(processedOrder);
		} catch( Exception exc ) {
			
			LOGGER.warning("persistProcessedOrder:" + exc.getMessage() );
			
			throw new YakShopException(exc.getMessage() );
		}
		LOGGER.info("Persisted order:" + processedOrder.toString() );
		
        RequestContextHolder.incrementWriteCount();

	}

	@SuppressWarnings("unchecked")
	public List<ProcessedOrder> getProcessedOrdersBeforeDay( int beforeDay ) {
		List<ProcessedOrder> orders = null;
		
	    Query query = pm.newQuery(ProcessedOrder.class);
        query.setFilter("forDay <= forDayParam");
        query.declareParameters("Integer forDayParam");
        query.setOrdering("forDay asc");

        try {
        	
        	orders = (List<ProcessedOrder>) pm.newQuery(query).execute(beforeDay);
        	if( orders != null ) {
        		LOGGER.info("getProcessedOrdersBeforeDay on day:" + beforeDay + " found " + orders.size() );
        	}

        } finally {
        	
        	query.closeAll();
        	
        }

        RequestContextHolder.incrementReadCount();
		
		return orders;
	}

	@SuppressWarnings("unchecked")
	public List<ProcessedOrder> getProcessedOrdersForCustomer( String customerName ) {
		List<ProcessedOrder> orders = null;
		
	    Query query = pm.newQuery(ProcessedOrder.class);
        query.setFilter("customerName == customerNameParam");
        query.declareParameters("String customerNameParam");
        query.setOrdering("forDay asc");

        try {
        	
        	orders = (List<ProcessedOrder>) pm.newQuery(query).execute(customerName);
        	if( orders != null ) {
        		LOGGER.info("getProcessedOrdersForCustomer for customer:" + customerName + " found " + orders.size() );
        	}

        } finally {
        	
        	query.closeAll();
        	
        }

        RequestContextHolder.incrementReadCount();
		
		return orders;
	}

	@SuppressWarnings("unchecked")
	public List<ProcessedOrder> getAllProcessedOrders(  ) {
		List<ProcessedOrder> orders = null;
		
	    Query query = pm.newQuery(ProcessedOrder.class);
        query.setOrdering("forDay asc");

        try {
        	
        	orders = (List<ProcessedOrder>) pm.newQuery(query).execute();
        	if( orders != null ) {
        		LOGGER.info("getAllProcessedOrders found " + orders.size() );
        	}

        } finally {
        	
        	query.closeAll();
        	
        }

        RequestContextHolder.incrementReadCount();
		
		return orders;
	}
}
